此篇記錄一下圖片傳輸的學習筆記,也順便帶大家了解~
首先建立一個上傳圖片的 input
// 加上 multiple 可上傳多個檔案
<input type="file" name="file" id="file" multiple>
上傳檔案後可以用 files
屬性抓出資料
我們可以觀察到他是 FileList,並不是陣列,且裡面有檔名、類型、大小等等的詳細資料,接下來讀取檔案有兩種方法,分別是 Blob URL
與 FileReader
,以下分開介紹
當我們拿到 FileList 後可以使用 URL.createObjectURL()
方法將圖片轉為 Blob URL
const file = document.querySelector('#myfile').files[0]
URL.createObjectURL(file)
// blob:http://127.0.0.1:5500/f0c69bbc-e8d7-4ba8-aaf2-ab8ab794da28
我們拿到的 Blob URL
是指向當前記憶體位址,也就是說可以直接在網址輸入並檢視圖片
我們亦可使用 Blob URL
來直接實現圖片預覽功能
首先新增一個 img
供預覽圖片用
<input type="file" name="file" id="file">
<img id="img">
接下來設定監聽事件,在上傳時將圖片顯示出來
const myFile = document.querySelector('#file')
myFile.addEventListener('change', function(e) {
const file = e.target.files[0]
const img = document.querySelector('#img')
img.src = URL.createObjectURL(file)
})
當然我們也可以使用 Blob URL
來下載自己上傳的圖片
我們改寫一下剛剛監聽的內容
const myFile = document.querySelector('#file')
myFile.addEventListener('change', function(e) {
const file = e.target.files[0]
// 創造一個 a 標籤
const downloadLink = document.createElement('a')
// 將 a 標籤的連結改為 Blob URL
downloadLink.href = URL.createObjectURL(file)
// 將下載的檔名設定為 file
downloadLink.download = 'file'
// 點擊標籤
downloadLink.click()
})
如此一來上傳的同時也下載了圖片
再來介紹另一個方法,FileReader
可以將檔案轉成各種格式
readAsText()
readAsDataURL()
: 轉換成 Base64 編碼readAsArrayBuffer()
readAsBinaryString()
const myFile = document.querySelector('#file')
myFile.addEventListener('change', function(e) {
// 取得檔案
const file = e.target.files[0]
// 宣告 FileReader
const reader = new FileReader()
// 進行格式轉換
// 檔案轉換完成後執行
reader.onload = function() {
// 可以用 reader.result 查看編譯結果
console.log(reader.result)
}
})
基本宣告方法皆相同,只差在轉換的格式不同,接下來就介紹一下格式
Text
預設使用 UTF-8
的編碼,將檔案轉換成文字
DataURL
使用 Base64 直接將圖片編碼,因此檔案大小越大,編碼長度也就越長,不過他與 Blob URL
不同,因為不是記憶體位址,所以可以將圖片繪出,且同樣可以做到預覽圖片與下載的功能
<input type="file" name="file" id="file">
<img id="img">
const myFile = document.querySelector('#file')
myFile.addEventListener('change', function(e) {
const file = e.target.files[0]
const reader = new FileReader()
// 轉換成 DataURL
reader.readAsDataURL(file)
reader.onload = function() {
// 將圖片 src 替換為 DataURL
img.src = reader.result
}
})
也同樣能實現下載功能
const myFile = document.querySelector('#file')
myFile.addEventListener('change', function(e) {
const file = e.target.files[0]
const reader = new FileReader()
// 轉換成 DataURL
reader.readAsDataURL(file)
reader.onload = function() {
// 創造一個 a 標籤
const downloadLink = document.createElement('a')
// 將 a 標籤的連結改為 DataURL
downloadLink.href = reader.result
// 將下載的檔名設定為 file
downloadLink.download = 'file'
// 點擊標籤
downloadLink.click()
}
})
ArrayBuffer
是一種原始二進制數據,可再將其編譯成 Blob
const myFile = document.querySelector('#file')
myFile.addEventListener('change', function(e) {
const file = e.target.files[0]
const reader = new FileReader()
// 轉換成 ArrayBuffer
reader.readAsArrayBuffer(file)
reader.onload = function() {
// 將 ArrayBuffer 轉成 Blob
// 後方 type 可填入需要的類型
const blob = new Blob([reader.result], { type: 'image/jpeg' })
// 亦可將 Blob 再次轉成 Blob URL
console.log(URL.createObjectURL(blob))
}
})
亦可直接將 ArrayBuffer
編譯為 DataURL
const myFile = document.querySelector('#file')
myFile.addEventListener('change', function(e) {
const file = e.target.files[0]
const reader = new FileReader()
// 轉換成 ArrayBuffer
reader.readAsArrayBuffer(file)
reader.onload = function() {
// 將 ArrayBuffer 轉換為 字串
const str = String.fromCharCode.apply(null, new Uint8Array(reader.result))
// 將其組成 DataURL
console.log('data:image/jpg;base64,' + btoa(str))
}
})
BinaryString
已經被 W3C 棄用,所以不建議使用
圖片與 canvas 可以互相轉換,如果不知道 canvas 是甚麼的話可以參考這邊
不管是 Blob URL
還是 DataURL
都可以將其轉成 canvas 繪製,首先我們先建立一個 canvas,然後使用 drawImage
方法將其繪製出來,使用之前介紹的 Blob URL
或是 DataURL
方法皆可
<input type="file" name="file" id="file">
<canvas id="mycanvas"></canvas>
const myFile = document.querySelector('#file')
const canvas = document.getElementById('mycanvas')
const ctx = canvas.getContext('2d')
myFile.addEventListener('change', function(e) {
const file = e.target.files[0]
// 宣告一個新圖片
let img = new Image()
img.src = URL.createObjectURL(file)
img.onload = function() {
// 設定 canvas 寬高等同圖片
canvas.width = img.width
canvas.height = img.height
// 將其繪製,並設定繪製的圖片寬高
ctx.drawImage(img, 0, 0, img.width, img.height)
}
})
const myFile = document.querySelector('#file')
const canvas = document.getElementById('mycanvas')
const ctx = canvas.getContext('2d')
myFile.addEventListener('change', function(e) {
const file = e.target.files[0]
const reader = new FileReader()
// 轉換成 DataURL
reader.readAsDataURL(file)
reader.onload = function() {
// 宣告一個新圖片
let img = new Image()
// 將圖片 src 替換為 DataURL
img.src = reader.result
img.onload = function() {
// 設定 canvas 寬高等同圖片
canvas.width = img.width
canvas.height = img.height
// 將其繪製,並設定繪製的圖片寬高
ctx.drawImage(img, 0, 0, img.width, img.height)
}
}
})
首先我們繪製一個 canvas
<canvas id="mycanvas" width="150" height="150"></canvas>
<img id="img">
const canvas = document.getElementById('mycanvas')
const ctx = canvas.getContext('2d')
canvas.width = 150
canvas.height = 150
ctx.fillRect(25, 25, 100, 100)
接下來使用 toDataURL
方法可將其轉為 DataURL
const img = document.getElementById('img')
const data = canvas.toDataURL('image/png')
img.src = data
轉換後也可使用上面學過的的功能下載唷!
可以用 toBlob
的方法將其轉為 Blob
canvas.toBlob(function(blob) {
console.log(blob)
})
同上先畫出 canvas 圖形,使用 getImageData
可以獲取 Uint8ClampedArray
的數據
ctx.getImageData(0, 0, 150, 150).data
其實圖片的處理就是各種編碼的轉換,只要熟悉各種資料類型與處理方式,就可以簡單的操控圖片囉!